#include "UserRegisterSection2.hpp"
#include "MyLogger.hpp"
#include "MySQLclient.hpp"
#include "Configuration.hpp"
#include <string.h>
#include <iostream>
using std::cout;
using std::endl;
using namespace std;

namespace wd
{
// 解析客户端数据（格式："username:encrypt"，与客户端完全对齐）
bool UserRegisterSection2::parseClientData(const string &data,string &username,string &clientEncrypt)
{
    LOG_INFO("Received data: %s", data.c_str()); // 添加这行
    size_t colonPos=data.find(':');
    if(colonPos==string::npos||colonPos==0||colonPos==data.size()-1)
    {
        return false;
    }
    //提取用户名: 从开始到冒号之前的部分
   username=data.substr(0,colonPos);
   //提取加密密码: 从冒号之后到字符串结束的部分
   clientEncrypt=data.substr(colonPos+1);
   return true;
}
// 从客户端加密密文中提取setting（用于存入数据库）
string UserRegisterSection2::extractSettingFromEncrypt(const string &clientEncrypt)
{
    // MD5-Crypt密文格式：$1$salt$hash → 提取前 " $1$salt$ " 部分
    // 从索引3开始找第三个$（第一个$在0，第二个在2）
    size_t thirdDollar=clientEncrypt.find('$',3);
    //setting长度不超过20
    if(thirdDollar==string::npos||thirdDollar>20)
    {
        return "";
    }
    return clientEncrypt.substr(0,thirdDollar+1);
}
void UserRegisterSection2::process()
{
    //校验数据包类型（必须是客户端注册阶段2的请求类型：10）
    if(_packet._type!=TASK_TYPE_REGISTER_SECTION2)
   {
        LOG_INFO("阶段2请求失败:类型%d",_packet._type);
        TLV resp(TASK_TYPE_LOGIN_SECTION2_RESP_ERROR,11,"Invalid type");
        _conn->sendInLoop(resp);
        return;
   }
   //解析客户端数据（格式："username:encrypt"，与客户端对齐）
   string username,clientEncrypt;
   if(!parseClientData(_packet._msg,username,clientEncrypt))
   {
        LOG_ERROR("阶段2解析客户端数据失败%s",_packet._msg.c_str());
        TLV resp(TASK_TYPE_LOGIN_SECTION2_RESP_ERROR,12,"Invalid format");
        _conn->sendInLoop(resp);
        return;
   }
   //校验加密密文长度
   if(clientEncrypt.size()!=34)
   {
       LOG_ERROR("阶段2解析数据长度失败%zu",clientEncrypt.size());
        TLV resp(TASK_TYPE_REGISTER_SECTION2_RESP_ERROR,16,"Encrypt too long");
        _conn->sendInLoop(resp);
        return;
   }

   //提取setting（从密文中提取，用于存入数据库）
   string setting=extractSettingFromEncrypt(clientEncrypt);
   if(setting.empty()||setting.find("$1$")!=0)
   {
       LOG_ERROR("提取setting失败%s",clientEncrypt.c_str());
        TLV resp(TASK_TYPE_REGISTER_SECTION2_RESP_ERROR,14,"Invalid encrypt");
        _conn->sendInLoop(resp);
        return;

   }

   //连接数据库
    MySQLclient mysql;
    Configuration* conf=Configuration::getInstance();
    if(!mysql.connect(conf->get("db_host"),
                      stoi(conf->get("db_port")),
                      conf->get("db_user"),
                      conf->get("db_pwd"),
                      conf->get("db_name")))
    {
       LOG_INFO("连接数据库失败");
       TLV resp(TASK_TYPE_LOGIN_SECTION1_RESP_ERROR,12,"System error");
        _conn->sendInLoop(resp);
        return;
    }

    // 插入SQL：name(用户名), setting(盐值前缀), encrypt(完整密文)
    std::string sql = "INSERT INTO user_registry (name, setting, encrypt) VALUES (?, ?, ?)";
    MYSQL_STMT* stmt = mysql_stmt_init(&mysql._conn);
    if(!stmt||mysql_stmt_prepare(stmt,sql.c_str(),sql.size())!=0)
    {
       LOG_ERROR("准备数据库失败%s",mysql_stmt_error(stmt));
       mysql_stmt_close(stmt);
       TLV resp(TASK_TYPE_REGISTER_SECTION2_RESP_ERROR,12,"System error");
        _conn->sendInLoop(resp);
        return;
    }

    // 绑定3个参数：username、setting、clientEncrypt到占位符？
    MYSQL_BIND bind[3];
    memset(bind,0,sizeof(bind));

    //绑定用户
    bind[0].buffer_type=MYSQL_TYPE_STRING;
    bind[0].buffer=(char*)username.c_str();
    bind[0].buffer_length=username.size();

    //绑定setting
    bind[1].buffer_type=MYSQL_TYPE_STRING;
    bind[1].buffer=(char*)setting.c_str();
    bind[1].buffer_length=setting.size();

    //绑定加密密文
    bind[2].buffer_type=MYSQL_TYPE_STRING;
    bind[2].buffer=(char*)clientEncrypt.c_str();
    bind[2].buffer_length=clientEncrypt.size();

    if(mysql_stmt_bind_param(stmt,bind)!=0)
    {
       LOG_ERROR("绑定失败%s",mysql_stmt_error(stmt));
       mysql_stmt_close(stmt);
       TLV resp(TASK_TYPE_REGISTER_SECTION2_RESP_ERROR,12,"System error");
        _conn->sendInLoop(resp);
        return;
    }
     // 6. 执行插入并处理结果、mysql_stmt_execute插入语句
    if (mysql_stmt_execute(stmt) == 0) { // 插入成功
        LOG_INFO("注册成功%s",username.c_str());
        TLV resp(TASK_TYPE_REGISTER_SECTION2_RESP_OK, 16, "Register success");
        _conn->sendInLoop(resp);
    } else { // 插入失败（如主键冲突）
        LOG_INFO("注册失败%s",mysql_stmt_error(stmt));
        TLV resp(TASK_TYPE_REGISTER_SECTION2_RESP_ERROR, 12, "System error");
        _conn->sendInLoop(resp);
    }

    // 7. 释放资源
    mysql_stmt_close(stmt);
}
}
